// Package pay_api provides order management functionality for payment operations.
package pay_api

import (
	"context"
	"fmt"

	"github.com/gogf/gf/v2/frame/g"
)

// OrderService provides order management operations
type OrderService struct {
	client ClientInterface
}

// NewOrderService creates a new order service instance
func NewOrderService(client ClientInterface) *OrderService {
	return &OrderService{
		client: client,
	}
}

// CreateOrder creates a new payment order
func (s *OrderService) CreateOrder(ctx context.Context, secret Secret, param CreateOrderParam) (*CreateOrderResp, error) {
	if err := s.validateCreateOrderParam(param); err != nil {
		return nil, err
	}

	reqData := g.Map{
		"agent_id":      param.AgentId,
		"merchant_id":   param.MerchantId,
		"order_id":      param.OrderId,
		"amount":        param.Amount,
		"pay_type":      param.PayType,
		"notify_url":    param.NotifyUrl,
		"jump_url":      param.JumpUrl,
		"jspay_flag":    param.JspayFlag,
		"openid":        param.Openid,
		"sub_openid":    param.SubOpenid,
		"sub_appid":     param.SubAppid,
		"attach":        param.Attach,
		"goods_tag":     param.GoodsTag,
		"goods_detail":  param.GoodsDetail,
		"time_start":    param.TimeStart,
		"time_expire":   param.TimeExpire,
		"auth_code":     param.AuthCode,
		"store_info":    param.StoreInfo,
		"terminal_info": param.TerminalInfo,
	}

	// Set authentication headers
	client := s.client.(*Client)
	client.client.SetHeaderMap(g.MapStrStr{
		"grpc-app-username": secret.Username,
		"grpc-app-key":      secret.Key,
	})

	resp, err := s.client.DoRequest(ctx, "POST", OrderCreateEndpoint, reqData)
	if err != nil {
		return nil, NewPayAPIErrorWithDetails(ErrAPIError, "创建订单失败", err.Error())
	}

	var result CommonRes[CreateOrderResp]
	if err := resp.Scan(&result); err != nil {
		return nil, NewPayAPIErrorWithDetails(ErrResponseParsing, "解析响应失败", err.Error())
	}

	if result.Code != 0 {
		return nil, NewPayAPIError(ErrAPIError, result.Message)
	}

	return &result.Data, nil
}

// QueryOrder queries order information
func (s *OrderService) QueryOrder(ctx context.Context, secret Secret, input QueryOrderInput) (*OrderInfo, error) {
	if err := s.validateQueryOrderInput(input); err != nil {
		return nil, err
	}

	reqData := g.Map{
		"agent_id":    input.AgentId,
		"merchant_id": input.MerchantId,
		"order_id":    input.OrderId,
	}

	// Set authentication headers
	client := s.client.(*Client)
	client.client.SetHeaderMap(g.MapStrStr{
		"grpc-app-username": secret.Username,
		"grpc-app-key":      secret.Key,
	})

	resp, err := s.client.DoRequest(ctx, "POST", OrderQueryEndpoint, reqData)
	if err != nil {
		return nil, NewPayAPIErrorWithDetails(ErrAPIError, "查询订单失败", err.Error())
	}

	var result CommonRes[OrderInfo]
	if err := resp.Scan(&result); err != nil {
		return nil, NewPayAPIErrorWithDetails(ErrResponseParsing, "解析响应失败", err.Error())
	}

	if result.Code != 0 {
		return nil, NewPayAPIError(ErrAPIError, result.Message)
	}

	return &result.Data, nil
}

// RefundOrder processes order refund
func (s *OrderService) RefundOrder(ctx context.Context, secret Secret, request RefundOrderRequest) ([]RefundOrderRes, error) {
	if err := s.validateRefundOrderRequest(request); err != nil {
		return nil, err
	}

	reqData := g.Map{
		"refundOrderParams": request.RefundOrderParams,
	}

	// Set authentication headers
	client := s.client.(*Client)
	client.client.SetHeaderMap(g.MapStrStr{
		"grpc-app-username": secret.Username,
		"grpc-app-key":      secret.Key,
	})

	resp, err := s.client.DoRequest(ctx, "POST", OrderRefundEndpoint, reqData)
	if err != nil {
		return nil, NewPayAPIErrorWithDetails(ErrAPIError, "退款失败", err.Error())
	}

	var result CommonRefundListRes[[]RefundOrderRes]
	if err := resp.Scan(&result); err != nil {
		return nil, NewPayAPIErrorWithDetails(ErrResponseParsing, "解析响应失败", err.Error())
	}

	if result.Code != 0 {
		return nil, NewPayAPIError(ErrAPIError, result.Message)
	}

	return result.List, nil
}

// Validation methods
func (s *OrderService) validateCreateOrderParam(param CreateOrderParam) error {
	if param.AgentId == "" {
		return NewPayAPIError(ErrInvalidRequest, "代理商编号不能为空")
	}
	if param.MerchantId == "" {
		return NewPayAPIError(ErrInvalidRequest, "商户号不能为空")
	}
	if param.OrderId == "" {
		return NewPayAPIError(ErrInvalidRequest, "订单号不能为空")
	}
	if param.Amount == "" {
		return NewPayAPIError(ErrInvalidRequest, "金额不能为空")
	}
	if param.PayType == "" {
		return NewPayAPIError(ErrInvalidRequest, "支付类型不能为空")
	}
	return nil
}

func (s *OrderService) validateQueryOrderInput(input QueryOrderInput) error {
	if input.AgentId == "" {
		return NewPayAPIError(ErrInvalidRequest, "代理商编号不能为空")
	}
	if input.MerchantId == "" {
		return NewPayAPIError(ErrInvalidRequest, "商户号不能为空")
	}
	if input.OrderId == "" {
		return NewPayAPIError(ErrInvalidRequest, "订单号不能为空")
	}
	return nil
}

func (s *OrderService) validateRefundOrderRequest(request RefundOrderRequest) error {
	if len(request.RefundOrderParams) == 0 {
		return NewPayAPIError(ErrInvalidRequest, "退款参数不能为空")
	}

	for i, param := range request.RefundOrderParams {
		if param.AgentId == "" {
			return NewPayAPIError(ErrInvalidRequest, fmt.Sprintf("第%d个退款参数：代理商编号不能为空", i+1))
		}
		if param.MerchantId == "" {
			return NewPayAPIError(ErrInvalidRequest, fmt.Sprintf("第%d个退款参数：商户号不能为空", i+1))
		}
		if param.OrderId == "" {
			return NewPayAPIError(ErrInvalidRequest, fmt.Sprintf("第%d个退款参数：订单号不能为空", i+1))
		}
		if param.RefundId == "" {
			return NewPayAPIError(ErrInvalidRequest, fmt.Sprintf("第%d个退款参数：退款单号不能为空", i+1))
		}
		if param.Amount == "" {
			return NewPayAPIError(ErrInvalidRequest, fmt.Sprintf("第%d个退款参数：退款金额不能为空", i+1))
		}
	}
	return nil
}

// Legacy functions for backward compatibility
// These functions maintain the original API while using the new service internally

// CreateOrder creates a payment order (legacy function)
func CreateOrder(ctx context.Context, secret Secret, param CreateOrderParam) (*CreateOrderResp, error) {
	client, err := NewClient(&Config{
		BaseURL:  secret.Baseurl,
		Username: secret.Username,
		Key:      secret.Key,
		Timeout:  30000000000, // 30 seconds
	})
	if err != nil {
		return nil, err
	}

	service := NewOrderService(client)
	return service.CreateOrder(ctx, secret, param)
}

// QueryOrder queries order information (legacy function)
func QueryOrder(ctx context.Context, secret Secret, input QueryOrderInput) (*OrderInfo, error) {
	client, err := NewClient(&Config{
		BaseURL:  secret.Baseurl,
		Username: secret.Username,
		Key:      secret.Key,
		Timeout:  30000000000, // 30 seconds
	})
	if err != nil {
		return nil, err
	}

	service := NewOrderService(client)
	return service.QueryOrder(ctx, secret, input)
}

// RefundOrder processes order refund (legacy function)
func RefundOrder(ctx context.Context, secret Secret, request RefundOrderRequest) ([]RefundOrderRes, error) {
	client, err := NewClient(&Config{
		BaseURL:  secret.Baseurl,
		Username: secret.Username,
		Key:      secret.Key,
		Timeout:  30000000000, // 30 seconds
	})
	if err != nil {
		return nil, err
	}

	service := NewOrderService(client)
	return service.RefundOrder(ctx, secret, request)
}
